/*
*
*	BUYER
*
*/


/* Some beliefs that are important:

toBuy( Item, MaxPrice ) --> used for init setup to buy an Item for MaxPrice
bought( Item, Price )	--> used to register final buying price
buying( Item, MaxPrice )--> used to keep track of currently buying ("want to buy") an item

*/



Beliefs:

	// allRepliesReveid if bidsSend and receivedReplies are equal, of if none bids are send.
	allRepliesReceived(Item, Bid) :- bidsSend(Item,Sends,Bid), findall(Seller,receivedReply(Item,Bid,Seller,_),Replies),	sort(Sends,Sellers), sort(Replies,Sellers).
	allRepliesReceived(Item, Bid) :- not bidsSend( Item, _, Bid ).



		
BeliefUpdates:
	
	{toBuy( Item, Price )}	
		HasAdoptedBuy( Item, Price ) 	
	{ not toBuy( Item, Price ), buying( Item, Price )}
	
		{ buying( Item, MaxPrice) }
	Bought( Item, Price )		
		{ buy(Item,MaxPrice), bought( Item, Price), not buying( Item, MaxPrice ) }

		{ buying( Item, _ ) }
	NewSellerForItem( Item, Seller )
		{ sellerForItem( Item, Seller) }

	 {sellerForItem(Item,Seller)}
	RemoveSeller(Item,Seller)	
	 {not sellerForItem(Item,Seller)}

		{ buying( Item, _ )  }
	BidsSend( Item, Sellers, Bid )
		{ bidsSend( Item, Sellers, Bid )}
	
	
	// GotoRound (or start the first one)		
		{ inRound( Item, BidOld ) }
	GotoRound( Item, Bid )
		{ not inRound( Item, BidOld ),
		 		 inRound( Item, Bid ) }
		  
		{ true }
	GotoRound( Item, Bid )
		{ inRound( Item, Bid ) }
			
		{ inRound( Item, Bid ) }
	ResetRound( Item )
		{ not inRound( Item, Bid ) }


		
	
		{ buying( Item, _ ) and inRound( Item, Bid )}
	ReceivedReply( Item, Bid, Seller, Result )
		{ receivedReply( Item, Bid, Seller, Result ) }
	
	
		{ bidsSend( Item, Sellers, Bid ) }
	ClearBidsSend( Item, Bid )
		{ not bidsSend( Item, Sellers, Bid ) }
		
		{true}
	ClearRound(Item,Bid)
		{not inRound(Item, Bid)}
	
	// Empty the received replies.
		{ receivedReply( Item, Bid, Seller, Result ) }
	ClearReceivedReplies( Item, Bid )
		{ not receivedReply( Item, Bid, Seller, Result ) }
			
		{ receivedReply( Item, Bid, Seller, Result ) }
	ClearReceivedReply( Item, Bid, Seller )
		{ not receivedReply( Item, Bid, Seller, Result ) }
					
		{}
	ClearReceivedReply( Item, Bid, Seller )
		{ not receivedReply( Item, Bid, Seller, accept ),
		  not receivedReply( Item, Bid, Seller, reject ) }
	
	{}
	ClearReceivedConfirm(Item,Bid,Seller)
	{	not receivedConfirm(Item,Bid,Seller,accept),
		not receivedConfirm(Item,Bid,Seller,reject)
	}
	
		{}
	ConfirmSellReceived( Item, Bid, Seller, Status )
		{ receivedConfirm( Item, Bid, Seller, Status ) }
				  
	
	
	// "Lock" the Auction system while updating the Sellers-list
		{ not updatingSellers( Item ) }
	UpdatingSellers(Item)
		{updatingSellers(Item)}
	
	
	// "Continue" the Auction with the new Sellers-list
		{ updatingSellers( Item ) }
	DoneUpdatingSellers(Item)
		{	not updatingSellers(Item) }
		


PG-rules:
	true <- toBuy( Item, MaxPrice ) |
	{
		adopta( buy( Item, MaxPrice ) );
		HasAdoptedBuy( Item, MaxPrice );
		send( maintainer, request, registerAndMatchRequest( Item ) )	
	}
	
	
	
	buy( Item, MaxPrice ) <- 	
		not inRound( Item, _ ) and not updatingSellers(Item)
		and bagof(Seller,sellerForItem(Item,Seller),Sellers) |
	{	
		print( "Starting Auction for Item" ); print( Item ); print( "and MaxPrice" ); print( MaxPrice );
		startAuction(Item,MaxPrice);
		skip
	}

	
PC-rules:
	startAuction(Item,MaxPrice) <-
		buying(Item,MaxPrice) |
	{
		doAuction(Item,MaxPrice,0)
	}

	
	doAuction(Item,MaxPrice,CurrentBid) <- 
		not updatingSellers(Item) 
		and bagof(Seller,sellerForItem(Item,Seller),Sellers) |
	{
		doAuctionRound(Item,CurrentBid,Sellers);
	
		
		while B( receivedReply(Item,CurrentBid,SellerAccept,accept) and buying( Item, _ ) ) do
		{
			// A Seller returned positive, now send confirmation
			ClearReceivedReply( Item, CurrentBid, SellerAccept );
		
			send( SellerAccept, request, confirmReply( Item, CurrentBid ) );
			B( receivedConfirm( Item, CurrentBid, SellerAccept, Status ) );
			if B( Status = accept ) then
			{
				
				print( "Yes, I Bought " ); print( Item ); print( "for" ); print( CurrentBid ); print( "from" ); print( SellerAccept );
				send(maintainer,inform,removeRequest(Item));
				clearRound( Item, CurrentBid );
				Bought( Item, CurrentBid )
			}
			else
			{
				// Confirmation rejected. Loop again in the while-loop if there's an other positive seller,
				// else continue with aution
				print( "Not accepted by Selling trader" ); print( SellerAccept )
			}
		};
		
		
		// Check if Item isn't bought in the mean time (see above while-loop)
		if B( buying( Item, _ ) ) then
		{
		
			if B(MaxPrice = CurrentBid  )
			then 
			{
				clearRound( Item, CurrentBid );
				print("Failed with maximum bid, so just do nothing until a new Seller...");
				skip
			}
			else
			{
				// continue auction
				clearRound( Item, CurrentBid );
				// Get the current bid (it may have set to 0 due a new Seller) //Frank removed inround(Item,Bid)
				if B( bagof(Seller3,sellerForItem(Item,Seller3),Sellers3) ) then {	doAuction(Item,MaxPrice,CurrentBid+1) }
			}
		}
	}
	
	
	// Clear all data of the current round
	clearRound( Item, Bid ) <- true |
	{
		if B( bidsSend( Item, _, Bid ) ) then { ClearBidsSend( Item, Bid ) };
		while B( receivedReply( Item, Bid, Seller, Result ) ) do
		{
			ClearReceivedReply( Item, Bid, Seller )
		};
		
		while B(receivedConfirm(Item,Bid,Seller,Result)) do
		{
			ClearReceivedConfirm(Item,Bid,Seller)
		};
		
		ClearRound(Item,Bid)
	}
	
	
	doAuctionRound(Item,Bid,Sellers) <- 
		buying(Item,_) |
	{
		GotoRound( Item, Bid );
		sendBids( Item, Bid, Sellers );
		B( allRepliesReceived( Item, Bid ) );
		print(allRepliesReceived( Item, Bid ));
		skip
	}
	
	

	
	
	/* 
	 * Message received from Maintainer with new sellers for requesting item.
	 * Sellers: The list of Sellers, that match requesting item.
	 * Item:    The item that is registered by the maintainer as request.
	 */
	message( Maintainer, inform, _, _, sellersForItem( Item, Sellers ) ) <- 
		maintainer(Maintainer) and buying(Item, Price ) |
	{
		UpdatingSellers(Item);
		newSellersForItem(Item,Sellers);
		resetRound( Item );
		DoneUpdatingSellers(Item);
		skip
	}
	
	
	/*
	 * Message received from Maintainer that an offer is removed.
	 */
	 message(Maintainer, inform, _, _, removedOffer(Item, Seller) ) <-
	 	maintainer(Maintainer) |
	 {
	 	if B(sellerForItem(Item,Seller)) then{
	 		RemoveSeller(Item,Seller)}
	 }
	
	
	
	
	/* 
	 * Message received from a Seller with a reply on an auction bid.
	 * Item: The item which is auctioned.
	 * Bid: The bid which is replied on.
	 * Result: Either accept or reject.
	 */
	message( Seller, inform, _, _, replyOnBid( Item, Bid, Result ) ) <- 
		buying( Item, _ ) and bidsSend( Item, Sellers, Bid ) 
		and member(Seller,Sellers) |
	{
		ReceivedReply( Item, Bid, Seller, Result );
		skip
	}
	
	
	/*
	 * Message received from a Sellet with a confirm of Sell
	 * Item: The item to buy
	 * Bid: The price of buying
	 * Status: "accept" or "reject"
	 */
	message( Seller, inform, _, _, confirmSell( Item, Bid, Status ) ) <- true |
	{
		ConfirmSellReceived( Item, Bid, Seller, Status )
	}
	
	
	// Helping function to register new Sellers (recursive)
	newSellersForItem( Item, [] ) <- buying( Item, _ ) | { skip }
	newSellersForItem( Item, [Seller | Rest] ) <- 
		buying( Item, _ )|
	{
		NewSellerForItem( Item, Seller );
		newSellersForItem( Item, Rest )
	}
	

	// Send bids to Sellers who are known to have Item		
	sendBids( Item, Bid, Sellers ) <- true |
	{
		print(bidsSend( Item, Sellers, Bid ));
		BidsSend( Item, Sellers, Bid );
		sendAll( Sellers, request, auctionBid( Item, Bid ) );
		skip
	}
	
	
	// Reset the round/auction in which we are currently in.
	resetRound( Item ) <- inRound( Item, Bid ) |
	{
		print( resetRound( Item,Bid ) );
		ResetRound( Item );
		clearRound( Item, Bid )
	}
	
	resetRound( Item ) <- true |
	{ skip }